﻿using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ServiceModel.Syndication;
using System.Xml;
using NColony.Dependencies.Contracts;
using NColony.Syndication.Receiver.Contracts;

namespace NColony.Syndication.Receiver
{
    /// <summary>
    /// RSS syndication reader.
    /// </summary>
    [Export(typeof(ISyndicationReader<ISyndicationFeed>))]
    public sealed class RssFeedReader : ISyndicationReader<ISyndicationFeed>
    {
        private readonly IDependencyManager dependencyManager;

        private readonly ISyndicationFeed feed;

        /// <summary>
        /// Initializes a new instance of the <see cref="RssFeedReader"/> class.
        /// </summary>
        [ImportingConstructor]
        public RssFeedReader(
            IDependencyManager dependencyManager,
            ISyndicationFeed feed)
        {
            if (dependencyManager == null) throw new ArgumentNullException("dependencyManager");
            if (feed == null) throw new ArgumentNullException("feed");

            this.dependencyManager = dependencyManager;
            this.feed = feed;
        }

        /// <summary>
        /// Gets the feed.
        /// </summary>
        /// <value>The feed.</value>
        public ISyndicationFeed Feed { get { return this.feed; } }

        /// <summary>
        /// Reads the specified XML reader.
        /// </summary>
        /// <param name="xmlReader">The XML reader.</param>
        public void Read(XmlReader xmlReader)
        {
            if (xmlReader == null) throw new ArgumentNullException("xmlReader");

            SyndicationFeed syndicationFeed = null;
            
            syndicationFeed = SyndicationFeed.Load(xmlReader);

            this.OnPropertyChanging("Feed");

            this.Feed.Title = syndicationFeed.Title.Text;
            
            this.Feed.Items.Clear();

            foreach (var item in syndicationFeed.Items)
            {
                var feedItem = this.dependencyManager.CreateInstance<ISyndicationFeedItem>();

                feedItem.Title = item.Title.Text;
                feedItem.PublishDate = item.PublishDate;
                
                this.Feed.Items.Add(feedItem);
            }

            this.OnPropertyChanged("Feed");
        }

        /// <summary>
        /// Occurs when a property value is changing.
        /// </summary>
        public event PropertyChangingEventHandler PropertyChanging;

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Called when [property changing].
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        private void OnPropertyChanging(string propertyName)
        {
            if (this.PropertyChanging != null)
            {
                this.PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
